<?php

App::uses('AppController', 'Controller');
App::uses('CakeEmail', 'Network/Email');

class ReservasController extends AppController {
    /**
     *         CONTROLLER DATA MEMBERS
     */

    /**
     * Nombre del controlador
     *
     * Nombre del controlador
     *
     * @var string
     */
    public $name = "Reservas";

    /**
     * Modelos que utiliza
     *
     * Los modelos que usa el controller. Por defecto
     * cake usa el singular basado en el nombre del modelo,
     * pero por asuntos del idioma siempre se ingresa el modelo
     * para evitar posibles problemas.
     *
     * @var array(string)
     */
    public $uses = array('Reserva', 'RecorridoRealizado', 'Recorrido', 'Parada', 'RutaParada', 'Ruta', 'RecorridoRealizadoParada', 'Bus', 'Horario');

    /**
     * Componentes que utiliza
     *
     * Componentes que utiliza el controlador
     *
     * @var array(string)
     */
    public $components = array("Session");    //make available packages of logic that are shared between controllers
    public $helpers = array("Html", "Form", "Js");

    /**
     *         CONTROLLER CALLBACKS METHODS
     */
    public function beforeFilter() {
        parent::beforeFilter();
        $this->set('configurationReservas', Configure::read('Reservas'));
    }

    // public function afterFilter() {
    // }
    // public function beforeRender() {
    // }

    /**
     *         CONTROLLER METHODS (ACTIONS)
     */

    /**
     * Action por defecto para las reservas
     *
     * Este es el metodo base de las reservas, en este metodo
     * se buscan las reservas almacenadas en el sistema y se
     * devuelven a la vista para que el usuario pueda realizar
     * acciones sobre ellas
     *
     * @return void
     */
    public function index() {

    }

    public function retrieve_all() {
        if ($this->request->is('ajax')) {
            $data = $this->request->data;

            foreach ($data['order'] as $i => $order) {
                $data['order'][$i] = array(
                    'column' => $data['columns'][$data['order'][$i]['column']]['data'],
                    'direction' => strtoupper($data['order'][$i]['dir'])
                );
            }

            $filter = array();
            foreach ($data['columns'] as $i => $column) {
                if ($column['searchable'] === "true" && !empty($column['search']['value'])) {
                    $filter[] = array(
                        'column' => $column['name'],
                        'value' => $column['search']['value']
                    );
                }
            }

            $models = $this->Reserva->findAll($start = $data['start'], $length = $data['length'], $order = $data['order'], $filter);
            $totalWithFilter = $this->Reserva->findCountAll($filter);
            $total = $this->Reserva->findCountAll();

            $this->set(array(
                'draw' => $data['draw'],
                'results' => $models,
                'recordsTotal' => $total,
                'recordsFiltered' => $totalWithFilter
            ));
            $this->set('_serialize', array('results', 'recordsTotal', 'draw', 'recordsFiltered'));
        } else {
            $this->autoRender = false;
        }
    }

    /**
     * Consultar la información de una reserva especifica
     *
     * En este metodo se busca la reserva según el parametro de
     * entrada $id, si dicho parametro es nulo o si no se encuentra
     * una reserva con ese identificador asociado se devuelve un error.
     * Por otro lado, si se encuentra la reserva, se devuelve su
     * información a la vista para que sea procesada.
     *
     *
     * @param int $id identifiacador de la reserva que se va a buscar.
     * @return void
     */
    public function ver($id = null) {
        if (!$id) {
            throw new NotFoundException('Reserva inválida');
        }
        $reserva = $this->Reserva->find("first", array(
            "conditions" => array("Reserva.id_reserva" => $id),
            "recursive" => 0
        ));
        if (!$reserva) {
            $this->Session->setFlash('Reserva inválida');
            throw new NotFoundException('Reserva inválida');
        }
        $this->set('reserva', $reserva);
    }

    /**
     * Adicionar una nueva reserva
     *
     * Encargado de enviar a la vista todas los recorridos activos y,
     * cuando haya un request por post, agregar una reserva nueva
     *
     * @return void
     */
    public function agregar() {
        $recorridos = $this->Recorrido->find('all', array(
            'conditions' => array('Recorrido.estado_recorrido' => 'activo')
        ));
        $rutas = Array();
        foreach ($recorridos as $recorrido) {
            if (!in_array($recorrido['Ruta']['nombre_ruta'], $rutas)) {
                $rutas[$recorrido['Ruta']['id_ruta']] = $recorrido['Ruta']['nombre_ruta'];
            }
        }
        $this->set(array("recorridos" => $rutas));

        $reservasNoUsadasUsuario = $this->Reserva->find('all', array(
            'conditions' => array('Reserva.id_usuario' => 1, 'Reserva.estado_reserva' => 'no usada'),
            'recursive' => -1,
            'order' => array('Reserva.fecha_modificacion_reserva DESC')
        ));

        if (count($reservasNoUsadasUsuario) >= intval(Configure::read('Reservas')["times_for_penalty"])) {
            $ultimaReserva = $reservasNoUsadasUsuario[0]['Reserva'];
            $ultimaFecha = strtotime($ultimaReserva['fecha_modificacion_reserva']);
            $fechaRevision = strtotime('-' . Configure::read('Reservas')["penalty_check_days_number"] . ' days', $ultimaFecha);
            $resCounter = 0;
            $castigoVigente = false;
            foreach ($reservasNoUsadasUsuario as $reserva) {
                $fechaRes = strtotime($reserva['Reserva']['fecha_modificacion_reserva']);
                if ($fechaRes <= $ultimaFecha && $fechaRes >= $fechaRevision) {
                    $resCounter++;
                }
                if ($fechaRes < $fechaRevision) {
                    break;
                }
            }
            if ($resCounter >= intval(Configure::read('Reservas')["times_for_penalty"])) {
                $fechaFinCastigo = strtotime(Configure::read('Reservas')["penalty_lenght"] . ' days', $ultimaFecha);
                if (strtotime(date('Y/m/j H:i:s')) < $fechaFinCastigo) {
                    $castigoVigente = true;
                }
            }
            if ($castigoVigente) {
                $this->Session->setFlash('No puedes hacer reservas, tienes un castigo vigente');
                $this->redirect(array('action' => 'index'));
            }
        }

        $phpCAS = $this->Session->read('phpCAS');
        if ($this->request->is('post')) {
            $this->Reserva->create();
            $this->Reserva->set(array(
                'terminos' => $this->request->data['Reserva']['terminos'],
                'id_parada' => $this->request->data['Reserva']['parada']
            ));
            $validatorReserva = $this->Reserva->validator();
            foreach ($validatorReserva as $field => $rules) {
                if (!in_array($field, array('terminos', 'id_parada'))) {
                    unset($validatorReserva[$field]);
                }
            }
            $this->Recorrido->create();
            $this->Recorrido->set(array(
                'id_ruta' => $this->request->data['Reserva']['ruta'],
                'id_horario' => $this->request->data['Reserva']['horario']
            ));
            $validatorRecorrido = $this->Recorrido->validator();
            foreach ($validatorRecorrido as $field => $rules) {
                if (!in_array($field, array('id_ruta', 'id_horario'))) {
                    unset($validatorRecorrido[$field]);
                }
            }
            $this->RecorridoRealizado->create();
            $this->RecorridoRealizado->set(array(
                'fecha_salida' => $this->request->data['Reserva']['calendario'] . " 00:00:00"
            ));
            $validatorRecorridoRealizado = $this->RecorridoRealizado->validator();
            foreach ($validatorRecorridoRealizado as $field => $rules) {
                if (!in_array($field, array('fecha_salida'))) {
                    unset($validatorRecorridoRealizado[$field]);
                }
            }
            if (!$this->Reserva->validates(array('fieldlist' => array('terminos', 'id_parada'))) ||
                    !$this->Recorrido->validates(array('fieldlist' => array('id_ruta', 'id_horario'))) ||
                    !$this->RecorridoRealizado->validates(array('fieldlist' => array('fecha_salida')))
            ) {
                $this->Session->setFlash("Datos de la reserva no válidos");
                return;
            }

            $recorrido = $this->Recorrido->find('first', array(
                'conditions' => array(
                    'Recorrido.estado_recorrido' => 'activo',
                    'Recorrido.id_ruta' => $this->request->data["Reserva"]["ruta"],
                    'Recorrido.id_horario' => $this->request->data["Reserva"]["horario"],
                )
            ));
            if (!$recorrido || empty($recorrido)) {
                $this->Session->setFlash("La Reserva no puede ser creada, no existe el recorrido seleccionado");
                return;
            }
            $recorrido_realizado = $this->RecorridoRealizado->find('first', array(
                'conditions' => array(
                    'RecorridoRealizado.estado_recorrido_realizado' => 'programado',
                    'RecorridoRealizado.fecha_salida' => $this->request->data["Reserva"]["calendario"],
                    'RecorridoRealizado.id_recorrido' => $recorrido["Recorrido"]["id_recorrido"],
                    'Reserva.estado_reserva' => 'programada',
                )
            ));
            $fecha_limite = date('Y/m/j');
            $fecha_limite = date('Y-m-d', strtotime($fecha_limite . ' + ' . Configure::read('Reservas')["make_date_limit"] . ' days'));
            if (date('Y-m-d', strtotime($this->request->data["Reserva"]["calendario"])) > $fecha_limite) {
                $this->Session->setFlash("La Reserva tiene como limite " . Configure::read('Reservas')["make_date_limit"] . " días en el futuro");
                return;
            }
            $horario = $recorrido["Horario"];
            $today = date('Y-m-d');
            if ($today == date('Y-m-d', strtotime($this->request->data["Reserva"]["calendario"]))) {
                $today = date('Y/m/j H:i:s');
                $todayHorario = date('Y/m/d') . ' ' . $horario["hora_salida"];
                $todayDT = new DateTime($today);
                $todayHorarioDT = new DateTime($todayHorario);
                $diff = $todayDT->diff($todayHorarioDT);
                $hourDiff = $diff->format('%r%h') + ($diff->i / 60);
                if (floatval($hourDiff) < floatval(Configure::read('Reservas')["make_time_deadline"])) {
                    $this->Session->setFlash("La Reserva debe realizarse con mínimo " . Configure::read('Reservas')["make_time_deadline"] . " horas de anticipación");
                    return;
                }
            }
            if (!$recorrido_realizado) {
                $this->RecorridoRealizado->create();
                $this->RecorridoRealizado->set(
                        array(
                            'estado_recorrido_realizado' => 'programado',
                            'fecha_salida' => $this->request->data["Reserva"]["calendario"],
                            "Recorrido" => array("id_recorrido" => $recorrido["Recorrido"]["id_recorrido"]),
                            "Bus" => array("id_bus" => $recorrido["Bus"]["id_bus"]),
                            "Conductor" => array("id_conductor" => null),
                            'puestos_reservados' => 1,
                            'puestos_ocupados' => 0,
                            'latitud' => 0,
                            'longitud' => 0,
                            'velocidad_promedio' => 0
                        )
                );
                $rr = $this->RecorridoRealizado->data;
                try {
                    $this->RecorridoRealizado->save($this->RecorridoRealizado->data, false);
                    $this->Reserva->create();
                    $this->Reserva->set(
                            array(
                                'id_usuario' => $phpCAS['attributes']['NumeroIdentificacion'],
                                'id_recorrido_realizado' => $this->RecorridoRealizado->id,
                                'fecha_creacion_reserva' => date('Y/m/j H:i:s'),
                                'fecha_modificacion_reserva' => date('Y/m/j H:i:s'),
                                'estado_reserva' => 'programada',
                                'id_parada' => $this->request->data["Reserva"]["parada"],
                                'terminos' => $this->request->data["Reserva"]["terminos"]
                            )
                    );
                    if ($this->Reserva->save($this->Reserva->data)) {
                        $this->_notificarReserva($rr);
                        $this->Session->setFlash('Reserva guardada exitosamente');
                        $this->redirect(array('action' => 'index'));
                    } else {
                        $this->Session->setFlash('Reserva no guardada');
                    }
                } catch (Exception $e) {
                    $this->Session->setFlash('Error en la creación de la reserva');
                }
            } else {
                $reserva_anterior = $this->Reserva->find('first', array(
                    'conditions' => array(
                        'Reserva.id_recorrido_realizado' => $recorrido_realizado["RecorridoRealizado"]["id_recorrido_realizado"],
                        'Reserva.id_usuario' => $phpCAS['attributes']['NumeroIdentificacion'],
                        'Reserva.estado_reserva' => 'programada',
                    )
                ));
                if ($reserva_anterior || !empty($reserva_anterior)) {
                    $this->Session->setFlash('Ya tienes una reserva para ese recorrido');
                    $this->redirect(array('action' => 'index'));
                }
                if ($recorrido_realizado["Bus"]["capacidad"] > $recorrido_realizado["RecorridoRealizado"]["puestos_ocupados"]) {
                    $recorrido_realizado["RecorridoRealizado"]["puestos_reservados"] ++;
                    $rr = $recorrido_realizado;
                    try {
                        $this->RecorridoRealizado->save($recorrido_realizado, false);
                        $this->Reserva->create();
                        $this->Reserva->set(
                                array(
                                    'id_usuario' => $phpCAS['attributes']['NumeroIdentificacion'],
                                    'id_recorrido_realizado' => $this->RecorridoRealizado->id,
                                    'fecha_creacion_reserva' => date('Y/m/j H:i:s'),
                                    'fecha_modificacion_reserva' => date('Y/m/j H:i:s'),
                                    'estado_reserva' => 'programada',
                                    'id_parada' => $this->request->data["Reserva"]["parada"],
                                    'terminos' => $this->request->data["Reserva"]["terminos"]
                                )
                        );
                        if ($this->Reserva->save($this->Reserva->data)) {
                            $this->_notificarReserva($rr);
                            $this->Session->setFlash('Reserva guardada exitosamente');
                            $this->redirect(array('action' => 'index'));
                        } else {
                            $this->Session->setFlash('Reserva no guardada');
                        }
                    } catch (Exception $e) {
                        $this->Session->setFlash('Error en la creación de la reserva');
                    }
                } else {
                    $this->Session->setFlash('Reserva no guardada, Recorrido Lleno');
                }
            }
        }
    }

    /**
     * Editar una reserva previamente almacenada
     *
     * Se verifica que el parametro $id no sea nulo y luego se busca la
     * reserva a editar, en caso de tener el parametro vacio o de no
     * encontrar la reserva se lanza una exception con el mensaje de
     * error correspondiente. Posteriormente se verifica si se están
     * almacenando los nuevos datos de la reserva, de ser asi se guardan
     * estos nuevos datos y el metodo termina. De lo contrario se asume
     * que se esta haciendo un get de la vista de editar y por eso se
     * devuelven los datos de la reserva para que sean presentados en la
     * vista de edición.
     *
     * @param int $id identifiacador de la reserva que se va a editar.
     * @return void
     */
    public function editar($id = null) {
        if (!$id) {
            throw new NotFoundException('Reserva inválida');
        }
        $reserva = $this->Reserva->find('all', array(
            'conditions' => array('Reserva.id_reserva' => $id),
            'recursive' => 2
        ));
        if (!$reserva) {
            throw new NotFoundException('Reserva inválida');
        }
        $phpCAS = $this->Session->read('phpCAS');
        $reservasNoUsadasUsuario = $this->Reserva->find('all', array(
            'conditions' => array('Reserva.id_usuario' => 1, 'Reserva.estado_reserva' => 'no usada'),
            'recursive' => -1,
            'order' => array('Reserva.fecha_modificacion_reserva DESC')
        ));

        if (count($reservasNoUsadasUsuario) >= intval(Configure::read('Reservas')["times_for_penalty"])) {
            $ultimaReserva = $reservasNoUsadasUsuario[0]['Reserva'];
            $ultimaFecha = strtotime($ultimaReserva['fecha_modificacion_reserva']);
            $fechaRevision = strtotime('-' . Configure::read('Reservas')["penalty_check_days_number"] . ' days', $ultimaFecha);
            $resCounter = 0;
            $castigoVigente = false;
            foreach ($reservasNoUsadasUsuario as $reserva) {
                $fechaRes = strtotime($reserva['Reserva']['fecha_modificacion_reserva']);
                if ($fechaRes <= $ultimaFecha && $fechaRes >= $fechaRevision) {
                    $resCounter++;
                }
                if ($fechaRes < $fechaRevision) {
                    break;
                }
            }
            if ($resCounter >= intval(Configure::read('Reservas')["times_for_penalty"])) {
                $fechaFinCastigo = strtotime(Configure::read('Reservas')["penalty_lenght"] . ' days', $ultimaFecha);
                if (strtotime(date('Y/m/j H:i:s')) < $fechaFinCastigo) {
                    $castigoVigente = true;
                }
            }
            if ($castigoVigente) {
                $this->Session->setFlash('No puedes hacer reservas, tienes un castigo vigente');
                $this->redirect(array('action' => 'index'));
            }
        }
        if ($reserva[0]["Reserva"]["estado_reserva"] != 'programada') {
            $this->Session->setFlash('La Reserva ya no puede ser modificada');
            $this->redirect(array('action' => 'index'));
        }

        if (date('Ymd') == date('Ymd', strtotime($reserva[0]["RecorridoRealizado"]["fecha_salida"]))) {
            $recorridoHorario = $this->Recorrido->find('all', array(
                'conditions' => array('Recorrido.id_recorrido' => $reserva[0]["RecorridoRealizado"]["Recorrido"]["id_recorrido"]),
                'recursive' => 0
            ));
            if (!$recorridoHorario) {
                throw new NotFoundException('Recorrido inválido');
            }
            $s = new DateTime(date('Y-m-d H:i:s'));
            $e = new DateTime(date('Y-m-d') . ' ' . $recorridoHorario[0]["Horario"]["hora_salida"]);
            $dd = date_diff($s, $e);
            $diferencia = $dd->format('%r%h');

            if (intval($diferencia) < intval(Configure::read('Reservas')["edit_time_deadline"])) {
                $this->Session->setFlash('La Reserva ya no puede ser modificada');
                $this->redirect(array('action' => 'index'));
            }
        } else {
            if (date('Ymd') > date('Ymd', strtotime($reserva[0]["RecorridoRealizado"]["fecha_salida"]))) {
                $this->Session->setFlash('La Reserva ya no puede ser modificada');
                $this->redirect(array('action' => 'index'));
            }
        }

        $recorridos = $this->Recorrido->find('all', array(
            'conditions' => array('Recorrido.estado_recorrido' => 'activo')
        ));
        $rutas = Array();
        foreach ($recorridos as $recorrido) {
            if (!in_array($recorrido['Ruta']['nombre_ruta'], $rutas)) {
                $rutas[$recorrido['Ruta']['id_ruta']] = $recorrido['Ruta']['nombre_ruta'];
            }
        }
        $this->set(array("recorridos" => $rutas));

        if ($this->request->is('post') || $this->request->is('put')) {
            $this->Reserva->create();
            $this->Reserva->set(array(
                'terminos' => $this->request->data['Reserva']['terminos'],
                'id_parada' => $this->request->data['Reserva']['parada']
            ));
            $validatorReserva = $this->Reserva->validator();
            foreach ($validatorReserva as $field => $rules) {
                if (!in_array($field, array('terminos', 'id_parada'))) {
                    unset($validatorReserva[$field]);
                }
            }
            $this->Recorrido->create();
            $this->Recorrido->set(array(
                'id_ruta' => $this->request->data['Reserva']['ruta'],
                'id_horario' => $this->request->data['Reserva']['horario']
            ));
            $validatorRecorrido = $this->Recorrido->validator();
            foreach ($validatorRecorrido as $field => $rules) {
                if (!in_array($field, array('id_ruta', 'id_horario'))) {
                    unset($validatorRecorrido[$field]);
                }
            }
            $this->RecorridoRealizado->create();
            $this->RecorridoRealizado->set(array(
                'fecha_salida' => $this->request->data['Reserva']['calendario'] . " 00:00:00"
            ));
            $validatorRecorridoRealizado = $this->RecorridoRealizado->validator();
            foreach ($validatorRecorridoRealizado as $field => $rules) {
                if (!in_array($field, array('fecha_salida'))) {
                    unset($validatorRecorridoRealizado[$field]);
                }
            }
            if (!$this->Reserva->validates(array('fieldlist' => array('terminos', 'id_parada'))) ||
                    !$this->Recorrido->validates(array('fieldlist' => array('id_ruta', 'id_horario'))) ||
                    !$this->RecorridoRealizado->validates(array('fieldlist' => array('fecha_salida')))
            ) {
                $this->Session->setFlash("Datos de la reserva no válidos");
                return;
            }

            $recorrido = $this->Recorrido->find('first', array(
                'conditions' => array(
                    'Recorrido.estado_recorrido' => 'activo',
                    'Recorrido.id_ruta' => $this->request->data["Reserva"]["ruta"],
                    'Recorrido.id_horario' => $this->request->data["Reserva"]["horario"],
                )
            ));
            if (!$recorrido || empty($recorrido)) {
                $this->Session->setFlash("La Reserva no puede ser creada, no existe el recorrido seleccionado");
                return;
            }
            $recorrido_realizado = $this->RecorridoRealizado->find('first', array(
                'conditions' => array(
                    'RecorridoRealizado.estado_recorrido_realizado' => 'programado',
                    'RecorridoRealizado.fecha_salida' => $this->request->data["Reserva"]["calendario"],
                    'RecorridoRealizado.id_recorrido' => $recorrido["Recorrido"]["id_recorrido"],
                )
            ));
            $fecha_limite = date('Y/m/j');
            $fecha_limite = date('Y-m-d', strtotime($fecha_limite . ' + ' . Configure::read('Reservas')["make_date_limit"] . ' days'));
            if (date('Y-m-d', strtotime($this->request->data["Reserva"]["calendario"])) > $fecha_limite) {
                $this->Session->setFlash("La Reserva tiene como limite " . Configure::read('Reservas')["make_date_limit"] . " días en el futuro");
                return;
            }
            $horario = $recorrido["Horario"];
            $today = date('Y-m-d');
            if ($today == date('Y-m-d', strtotime($this->request->data["Reserva"]["calendario"]))) {
                $today = date('Y/m/j H:i:s');
                $todayHorario = date('Y/m/d') . ' ' . $horario["hora_salida"];
                $todayDT = new DateTime($today);
                $todayHorarioDT = new DateTime($todayHorario);
                $diff = $todayDT->diff($todayHorarioDT);
                $hourDiff = $diff->format('%r%h') + ($diff->i / 60);
                if (floatval($hourDiff) < floatval(Configure::read('Reservas')["make_time_deadline"])) {
                    $this->Session->setFlash("La Reserva debe realizarse con mínimo " . Configure::read('Reservas')["make_time_deadline"] . " horas de anticipación");
                    return;
                }
            }
            if (!$recorrido_realizado) {
                $this->RecorridoRealizado->create();
                $this->RecorridoRealizado->set(
                        array(
                            'estado_recorrido_realizado' => 'programado',
                            'fecha_salida' => $this->request->data["Reserva"]["calendario"],
                            "Recorrido" => array("id_recorrido" => $recorrido["Recorrido"]["id_recorrido"]),
                            "Bus" => array("id_bus" => $recorrido["Bus"]["id_bus"]),
                            "Conductor" => array("id_conductor" => null),
                            'puestos_reservados' => 1,
                            'puestos_ocupados' => 0,
                            'latitud' => 0,
                            'longitud' => 0,
                            'velocidad_promedio' => 0
                        )
                );
                $rr = $this->RecorridoRealizado->data;
                try {
                    $this->RecorridoRealizado->save($this->RecorridoRealizado->data, false);
                    $this->Reserva->create();
                    $this->Reserva->set(
                            array(
                                'id_usuario' => $phpCAS['attributes']['NumeroIdentificacion'],
                                'id_recorrido_realizado' => $this->RecorridoRealizado->id,
                                'fecha_creacion_reserva' => date('Y/m/j H:i:s'),
                                'fecha_modificacion_reserva' => date('Y/m/j H:i:s'),
                                'estado_reserva' => 'programada',
                                'id_reserva' => $id,
                                'id_parada' => $this->request->data["Reserva"]["parada"],
                                'terminos' => $this->request->data["Reserva"]["terminos"]
                            )
                    );
                    if ($this->Reserva->save($this->Reserva->data)) {
                        $this->_notificarReserva($rr);
                        $this->Session->setFlash('Reserva guardada exitosamente');
                        $this->redirect(array('action' => 'index'));
                    } else {
                        $this->Session->setFlash('Reserva no guardada');
                    }
                } catch (Exception $e) {
                    $this->Session->setFlash('Error en la creación de la reserva');
                }
            } else {
                $reserva_anterior = $this->Reserva->find('first', array(
                    'conditions' => array(
                        'Reserva.id_recorrido_realizado' => $recorrido_realizado["RecorridoRealizado"]["id_recorrido_realizado"],
                        'Reserva.id_usuario' => $phpCAS['attributes']['NumeroIdentificacion'],
                        'Reserva.estado_reserva' => 'programada',
                    )
                ));
                if ($reserva_anterior || !empty($reserva_anterior)) {
                    if ($id != $reserva_anterior['Reserva']['id_reserva']) {
                        $this->Session->setFlash('Ya tienes una reserva para ese recorrido');
                        $this->redirect(array('action' => 'index'));
                    }
                }
                if ($recorrido_realizado["Bus"]["capacidad"] > $recorrido_realizado["RecorridoRealizado"]["puestos_ocupados"]) {
                    $recorrido_realizado["RecorridoRealizado"]["puestos_reservados"] ++;
                    $rr = $recorrido_realizado;
                    try {
                        $this->RecorridoRealizado->save($recorrido_realizado, false);
                        $this->Reserva->create();
                        $this->Reserva->set(
                                array(
                                    'id_usuario' => $phpCAS['attributes']['NumeroIdentificacion'],
                                    'id_recorrido_realizado' => $this->RecorridoRealizado->id,
                                    'estado_reserva' => 'programada',
                                    'id_reserva' => $id,
                                    'id_parada' => $this->request->data["Reserva"]["parada"],
                                    'terminos' => $this->request->data["Reserva"]["terminos"]
                                )
                        );
                        if ($this->Reserva->save($this->Reserva->data)) {
                            $this->_notificarReserva($rr);
                            $this->Session->setFlash('Reserva guardada exitosamente');
                            $this->redirect(array('action' => 'index'));
                        } else {
                            $this->Session->setFlash('Reserva no guardada');
                        }
                    } catch (Exception $e) {
                        $this->Session->setFlash('Error en la creación de la reserva');
                    }
                } else {
                    $this->Session->setFlash('Reserva no guardada, Recorrido Lleno');
                }
            }
        }

        if (!$this->request->data) {
            $this->request->data = $reserva[0];
            $this->request->data["Reserva"]["ruta"] = $reserva[0]["RecorridoRealizado"]["Recorrido"]["id_ruta"];
            $this->request->data["Reserva"]["calendario"] = $reserva[0]["RecorridoRealizado"]["fecha_salida"];
        }
    }

    /**
     * Borra una reserva de la base de datos
     *
     * Se verifica que el request no sea un get para
     * minimzar la probabilidad de errores. Luego se borra la reserva
     * indicada.
     *
     * @param int $id identifiacador de la reserva que se va a borrar.
     * @return void
     */
    public function borrar($id) {
        if (!$id) {
            throw new NotFoundException('Reserva inválida');
        }
        $reserva = $this->Reserva->find('all', array(
            'conditions' => array('Reserva.id_reserva' => $id),
            'recursive' => 2
        ));
        if (!$reserva) {
            throw new NotFoundException('Reserva inválida');
        }

        if ($reserva[0]["Reserva"]["estado_reserva"] != 'programada') {
            $this->Session->setFlash('La Reserva ya no puede ser modificada');
            $this->redirect(array('action' => 'index'));
        }

        if (date('Ymd') == date('Ymd', strtotime($reserva[0]["RecorridoRealizado"]["fecha_salida"]))) {
            $recorridoHorario = $this->Recorrido->find('all', array(
                'conditions' => array('Recorrido.id_recorrido' => $reserva[0]["RecorridoRealizado"]["Recorrido"]["id_recorrido"]),
                'recursive' => 0
            ));
            if (!$recorridoHorario) {
                throw new NotFoundException('Recorrido inválido');
            }
            $s = new DateTime(date('Y-m-d H:i:s'));
            $e = new DateTime(date('Y-m-d') . ' ' . $recorridoHorario[0]["Horario"]["hora_salida"]);
            $dd = date_diff($s, $e);
            $diferencia = $dd->format('%r%h');

            if (intval($diferencia) < intval(Configure::read('Reservas')["cancel_time_deadline"])) {
                $this->Session->setFlash('La Reserva ya no puede ser modificada');
                $this->redirect(array('action' => 'index'));
            }
        } else {
            if (date('Ymd') > date('Ymd', strtotime($reserva[0]["RecorridoRealizado"]["fecha_salida"]))) {
                $this->Session->setFlash('La Reserva ya no puede ser modificada');
                $this->redirect(array('action' => 'index'));
            }
        }

        if ($this->Reserva->delete($id)) {
            $this->Session->setFlash('Reserva ha sido cancelada exitosamente');
        } else {
            $this->Session->setFlash('La Reserva no pudo cancelarse');
        }
        $this->redirect(array('action' => 'index'));
    }

    /**
     * Agrega una reserva cuyos datos vienen por ajax
     *
     * Se verifica que el request no sea un get para
     * minimzar la probabilidad de errores. Luego se
     * agrega la reserva indicada verificando los castigos vigentes y
     * creando un recorrido realizado de ser necesario
     *
     * @param int $id identifiacador de la reserva que se va a borrar.
     * @return string(json) resultado
     */
    public function agregar_ajax() {
        $this->autoRender = false;
        $phpCAS = $this->Session->read('phpCAS');
        $reservasNoUsadasUsuario = $this->Reserva->find('all', array(
            'conditions' => array('Reserva.id_usuario' => 1, 'Reserva.estado_reserva' => 'no usada'),
            'recursive' => -1,
            'order' => array('Reserva.fecha_modificacion_reserva DESC')
        ));

        if (count($reservasNoUsadasUsuario) >= intval(Configure::read('Reservas')["times_for_penalty"])) {
            $ultimaReserva = $reservasNoUsadasUsuario[0]['Reserva'];
            $ultimaFecha = strtotime($ultimaReserva['fecha_modificacion_reserva']);
            $fechaRevision = strtotime('-' . Configure::read('Reservas')["penalty_check_days_number"] . ' days', $ultimaFecha);
            $resCounter = 0;
            $castigoVigente = false;
            foreach ($reservasNoUsadasUsuario as $reserva) {
                $fechaRes = strtotime($reserva['Reserva']['fecha_modificacion_reserva']);
                if ($fechaRes <= $ultimaFecha && $fechaRes >= $fechaRevision) {
                    $resCounter++;
                }
                if ($fechaRes < $fechaRevision) {
                    break;
                }
            }
            if ($resCounter >= intval(Configure::read('Reservas')["times_for_penalty"])) {
                $fechaFinCastigo = strtotime(Configure::read('Reservas')["penalty_lenght"] . ' days', $ultimaFecha);
                if (strtotime(date('Y/m/j H:i:s')) < $fechaFinCastigo) {
                    $castigoVigente = true;
                }
            }
            if ($castigoVigente) {
                $message = "Castigo Vigente";
                $data = compact("message");
                return json_encode($data, JSON_UNESCAPED_UNICODE);
            }
        }

        if ($this->request->is('post')) {
            $this->Reserva->create();
            $recorrido = $this->Recorrido->find('first', array(
                'conditions' => array(
                    'Recorrido.estado_recorrido' => 'activo',
                    'Recorrido.id_ruta' => $this->request->data["Reserva"]["ruta"],
                    'Recorrido.id_horario' => $this->request->data["Reserva"]["horario"],
                )
            ));
            if (!$recorrido || empty($recorrido)) {
                $message = "La Reserva no puede ser creada, no existe el recorrido seleccionado";
                $data = compact("message");
                return json_encode($data, JSON_UNESCAPED_UNICODE);
            }
            $recorrido_realizado = $this->RecorridoRealizado->find('first', array(
                'conditions' => array(
                    'RecorridoRealizado.estado_recorrido_realizado' => 'programado',
                    'RecorridoRealizado.fecha_salida' => $this->request->data["Reserva"]["calendario"],
                    'RecorridoRealizado.id_recorrido' => $recorrido["Recorrido"]["id_recorrido"],
                )
            ));
            $fecha_limite = date('Y/m/j');
            $fecha_limite = date('Y-m-d', strtotime($fecha_limite . ' + ' . Configure::read('Reservas')["make_date_limit"] . ' days'));
            if (date('Y-m-d', strtotime($this->request->data["Reserva"]["calendario"])) > $fecha_limite) {
                $message = "La Reserva tiene como limite " . Configure::read('Reservas')["make_date_limit"] . " días en el futuro";
                $data = compact("message");
                return json_encode($data, JSON_UNESCAPED_UNICODE);
            }
            $horario = $recorrido["Horario"];
            $today = date('Y-m-d');
            if ($today == date('Y-m-d', strtotime($this->request->data["Reserva"]["calendario"]))) {
                $today = date('Y/m/j H:i:s');
                $todayHorario = date('Y/m/d') . ' ' . $horario["hora_salida"];
                $todayDT = new DateTime($today);
                $todayHorarioDT = new DateTime($todayHorario);
                $diff = $todayDT->diff($todayHorarioDT);
                $hourDiff = $diff->format('%r%h') + ($diff->i / 60);
                if (floatval($hourDiff) < floatval(Configure::read('Reservas')["make_time_deadline"])) {
                    $message = "La Reserva debe realizarse con mínimo " . Configure::read('Reservas')["make_time_deadline"] . " horas de anticipación";
                    $data = compact("message");
                    return json_encode($data, JSON_UNESCAPED_UNICODE);
                }
            }
            if (!$recorrido_realizado) {
                $this->RecorridoRealizado->create();
                $this->RecorridoRealizado->set(
                        array(
                            'estado_recorrido_realizado' => 'programado',
                            'fecha_salida' => $this->request->data["Reserva"]["calendario"],
                            "Recorrido" => array("id_recorrido" => $recorrido["Recorrido"]["id_recorrido"]),
                            "Bus" => array("id_bus" => $recorrido["Bus"]["id_bus"]),
                            "Conductor" => array("id_conductor" => null),
                            'puestos_reservados' => 1,
                            'puestos_ocupados' => 0,
                            'latitud' => 0,
                            'longitud' => 0,
                            'velocidad_promedio' => 0
                        )
                );
                $rr = $this->RecorridoRealizado->data;
                try {
                    $this->RecorridoRealizado->save($this->RecorridoRealizado->data, false);
                    $this->Reserva->create();
                    $this->Reserva->set(
                            array(
                                'id_usuario' => $phpCAS['attributes']['NumeroIdentificacion'],
                                'id_recorrido_realizado' => $this->RecorridoRealizado->id,
                                'fecha_creacion_reserva' => date('Y/m/j H:i:s'),
                                'fecha_modificacion_reserva' => date('Y/m/j H:i:s'),
                                'estado_reserva' => 'programada',
                                'id_parada' => $this->request->data["Reserva"]["parada"],
                                'terminos' => $this->request->data["Reserva"]["terminos"]
                            )
                    );
                    if ($this->Reserva->save($this->Reserva->data)) {
                        $this->_notificarReserva($rr);
                        $datos_adicionales = array();
                        $datos_adicionales["Ruta"] = $this->Ruta->find('first', array(
                                    'conditions' => array("Ruta.id_ruta" => $this->request->data["Reserva"]["ruta"]),
                                    'recursive' => -1,
                                ))["Ruta"];
                        $datos_adicionales["Horario"] = $this->Horario->find('first', array(
                                    'conditions' => array("Horario.id_horario" => $this->request->data["Reserva"]["horario"]),
                                    'recursive' => -1,
                                ))["Horario"];
                        $parada_origen = $this->RutaParada->find('first', array(
                            'conditions' => array("RutaParada.id_ruta" => $this->request->data["Reserva"]["ruta"]),
                            'recursive' => 1,
                            'order' => array('RutaParada.orden_ruta ASC'),
                        ));
                        $parada_destino = $this->RutaParada->find('first', array(
                            'conditions' => array("RutaParada.id_ruta" => $this->request->data["Reserva"]["ruta"]),
                            'recursive' => 1,
                            'order' => array('RutaParada.orden_ruta DESC'),
                        ));

                        $reserva_details = array(
                            "id_reserva" => $this->Reserva->id,
                            "parada_origen" => $parada_origen["Parada"]["nombre_parada"],
                            "parada_destino" => $parada_destino["Parada"]["nombre_parada"],
                            "ruta" => $datos_adicionales["Ruta"]["nombre_ruta"],
                            "fecha" => date("Y/m/j", strtotime($this->request->data["Reserva"]["calendario"])),
                            "hora" => date("G:i", strtotime($datos_adicionales["Horario"]["hora_salida"]))
                        );

                        $message = "Reserva almacenada exitosamente";

                        $data = compact("reserva_details", "message");
                        return json_encode($data, JSON_UNESCAPED_UNICODE);
                    } else {
                        $errors = $this->Reserva->invalidFields();
                        $data = compact("errors");
                        return json_encode($data, JSON_UNESCAPED_UNICODE);
                    }
                } catch (Exception $e) {
                    $message = "Error en la creación de la reserva";
                    $data = compact("message");
                    return json_encode($data, JSON_UNESCAPED_UNICODE);
                }
            } else {
                $reserva_anterior = $this->Reserva->find('first', array(
                    'conditions' => array(
                        'Reserva.id_recorrido_realizado' => $recorrido_realizado["RecorridoRealizado"]["id_recorrido_realizado"],
                        'Reserva.id_usuario' => $phpCAS['attributes']['NumeroIdentificacion'],
                        'Reserva.estado_reserva' => 'programada',
                    )
                ));
                if ($reserva_anterior || !empty($reserva_anterior)) {
                    $message = "Ya tienes una reserva para ese recorrido";
                    $data = compact("message");
                    return json_encode($data, JSON_UNESCAPED_UNICODE);
                }
                if ($recorrido_realizado["Bus"]["capacidad"] > $recorrido_realizado["RecorridoRealizado"]["puestos_ocupados"]) {
                    $recorrido_realizado["RecorridoRealizado"]["puestos_reservados"] ++;
                    $rr = $recorrido_realizado;
                    try {
                        $this->RecorridoRealizado->save($recorrido_realizado, false);
                        $this->Reserva->create();
                        $this->Reserva->set(
                                array(
                                    'id_usuario' => $phpCAS['attributes']['NumeroIdentificacion'],
                                    'id_recorrido_realizado' => $this->RecorridoRealizado->id,
                                    'fecha_creacion_reserva' => date('Y/m/j H:i:s'),
                                    'fecha_modificacion_reserva' => date('Y/m/j H:i:s'),
                                    'estado_reserva' => 'programada',
                                    'id_parada' => $this->request->data["Reserva"]["parada"],
                                    'terminos' => $this->request->data["Reserva"]["terminos"]
                                )
                        );
                        if ($this->Reserva->save($this->Reserva->data)) {
                            $this->_notificarReserva($rr);
                            $datos_adicionales = array();
                            $datos_adicionales["Ruta"] = $this->Ruta->find('first', array(
                                        'conditions' => array("Ruta.id_ruta" => $this->request->data["Reserva"]["ruta"]),
                                        'recursive' => -1,
                                    ))["Ruta"];
                            $datos_adicionales["Horario"] = $this->Horario->find('first', array(
                                        'conditions' => array("Horario.id_horario" => $this->request->data["Reserva"]["horario"]),
                                        'recursive' => -1,
                                    ))["Horario"];
                            $parada_origen = $this->RutaParada->find('first', array(
                                'conditions' => array("RutaParada.id_ruta" => $this->request->data["Reserva"]["ruta"]),
                                'recursive' => 1,
                                'order' => array('RutaParada.orden_ruta ASC'),
                            ));
                            $parada_destino = $this->RutaParada->find('first', array(
                                'conditions' => array("RutaParada.id_ruta" => $this->request->data["Reserva"]["ruta"]),
                                'recursive' => 1,
                                'order' => array('RutaParada.orden_ruta DESC'),
                            ));

                            $reserva_details = array(
                                "id_reserva" => $this->Reserva->id,
                                "parada_origen" => $parada_origen["Parada"]["nombre_parada"],
                                "parada_destino" => $parada_destino["Parada"]["nombre_parada"],
                                "ruta" => $datos_adicionales["Ruta"]["nombre_ruta"],
                                "fecha" => date("Y/m/j", strtotime($this->request->data["Reserva"]["calendario"])),
                                "hora" => date("G:i", strtotime($datos_adicionales["Horario"]["hora_salida"]))
                            );

                            $message = "Reserva almacenada exitosamente";

                            $data = compact("reserva_details", "message");
                            return json_encode($data, JSON_UNESCAPED_UNICODE);
                        } else {
                            $errors = $this->Reserva->invalidFields();
                            $data = compact("errors");
                            return json_encode($data, JSON_UNESCAPED_UNICODE);
                        }
                    } catch (Exception $e) {
                        $message = "Error en la creación de la reserva";
                        $data = compact("message");
                        return json_encode($data, JSON_UNESCAPED_UNICODE);
                    }
                } else {
                    $message = "Reserva no guardada, Recorrido Lleno";
                    $data = compact("message");
                    return json_encode($data, JSON_UNESCAPED_UNICODE);
                }
            }
        }
    }

    /**
     * Notifica via email a los usuarios que hayan realizado una reserva
     *
     * Se obtiene la información necesaria y luego se envía el correo
     * al usuario que hizo la reserva
     *
     * @param objeto $rr recorrido realizado al que se le realizo la reserva.
     * @return void
     */
    public function _notificarReserva($rr = null) {
        $phpCAS = $this->Session->read('phpCAS');
        if (empty($rr["Recorrido"]["id_horario"])) {
            $recorrido = $this->Recorrido->find('all', array(
                'recursive' => 0,
                'conditions' => array(
                    'Recorrido.id_recorrido' => $rr["Recorrido"]["id_recorrido"]
                )
            ));
            $placa = $recorrido[0]["Bus"]["placa"];
            $capacidad = $recorrido[0]["Bus"]["capacidad"];
            $empresa = $recorrido[0]["Bus"]["empresa"];
            $hora_salida = $recorrido[0]["Horario"]["hora_salida"];
            $id_ruta = $recorrido[0]["Ruta"]["id_ruta"];
        } else {
            $placa = $rr["Bus"]["placa"];
            $capacidad = $rr["Bus"]["capacidad"];
            $empresa = $rr["Bus"]["empresa"];
            $horario = $this->Horario->find('all', array(
                'recursive' => 0,
                'conditions' => array(
                    'Horario.id_horario' => $rr["Recorrido"]["id_horario"]
                )
            ));
            $hora_salida = $horario[0]["Horario"]["hora_salida"];
            $id_ruta = $rr["Recorrido"]["id_ruta"];
        }

        $rutas_paradas = $this->RutaParada->find('all', array(
            'recursive' => 1,
            'conditions' => array(
                'RutaParada.id_ruta' => $id_ruta
            )
        ));
        $origenEnc = false;
        $destinoEnc = false;
        foreach ($rutas_paradas as $rp) {
            if ($rp["RutaParada"]["tipo_parada"] == "origen") {
                $origenEnc = true;
                $origen = $rp["Parada"]["nombre_parada"];
            }
            if ($rp["RutaParada"]["tipo_parada"] == "destino") {
                $destinoEnc = true;
                $destino = $rp["Parada"]["nombre_parada"];
            }
            if ($origenEnc && $destinoEnc) {
                break;
            }
        }
        $correo = $phpCAS['attributes']['CorreoElectronico'];
        $corrArray = explode(";", $correo);
        $correo = $corrArray[(count($corrArray) - 1)];
        $Email = new CakeEmail('default');
        $Email->template("reserva", "email_miBus")->emailFormat('both');
        $Email->to($correo);
        $Email->subject("Su Reserva ha sido Guardada");
        $Email->viewVars(array(
            'placa' => $placa,
            'capacidad' => $capacidad,
            'empresa' => $empresa,
            'reservedSpots' => $rr["RecorridoRealizado"]["puestos_reservados"],
            'departure' => date("Y/m/d", strtotime($rr["RecorridoRealizado"]["fecha_salida"])),
            'state' => $rr["RecorridoRealizado"]["estado_recorrido_realizado"],
            'departureTime' => date('h:i A', strtotime($hora_salida)),
            'origin' => $origen,
            'destiny' => $destino
        ));
        $Email->send("");
    }

}
